import os
import platform
import psutil
import socket
import datetime
import subprocess
from typing import Dict, List, Union, Any
import time
import sys
import json


class SysMonitorService:
    @staticmethod
    def get_server_info() -> Dict[str, Any]:
        """获取服务器所有信息"""
        return {
            'cpu': SysMonitorService.get_cpu_info(),
            'mem': SysMonitorService.get_mem_info(),
            'sys': SysMonitorService.get_sys_info(),
            'node': SysMonitorService.get_process_info(),
            'sysFiles': SysMonitorService.get_sys_files(),
            'nodeEnv': SysMonitorService.get_python_env()
        }

    @staticmethod
    def format_date(date: datetime.datetime) -> str:
        """格式化日期"""
        return date.strftime("%Y-%m-%d %H:%M:%S")

    @staticmethod
    def format_uptime(seconds: float) -> str:
        """格式化运行时间"""
        days = int(seconds // (24 * 3600))
        hours = int((seconds % (24 * 3600)) // 3600)
        minutes = int((seconds % 3600) // 60)
        remaining_seconds = int(seconds % 60)
        return f"{days}天 {hours}小时 {minutes}分钟 {remaining_seconds}秒"

    @staticmethod
    def get_python_env() -> Dict[str, str]:
        """获取Python环境信息"""
        start_time = datetime.datetime.fromtimestamp(
            psutil.Process(os.getpid()).create_time()
        )
        uptime = time.time() - psutil.Process(os.getpid()).create_time()

        return {
            'name': 'Python',
            'version': platform.python_version(),
            'startTime': SysMonitorService.format_date(start_time),
            'runTime': SysMonitorService.format_uptime(uptime),
            'home': sys.executable
        }

    @staticmethod
    def get_sys_files() -> List[Dict[str, Union[str, float]]]:
        """获取系统文件信息"""
        sys_files = []

        for partition in psutil.disk_partitions():
            if os.name == 'nt':
                if 'cdrom' in partition.opts or partition.fstype == '':
                    continue
            try:
                usage = psutil.disk_usage(partition.mountpoint)
                sys_files.append({
                    'dirName': partition.mountpoint,
                    'sysTypeName': partition.fstype,
                    'typeName': 'Local Fixed Disk',
                    'total': round(usage.total / (1024 ** 3), 2),  # Convert to GB
                    'free': round(usage.free / (1024 ** 3), 2),
                    'used': round(usage.used / (1024 ** 3), 2),
                    'usage': usage.percent
                })
            except Exception:
                continue

        return sys_files

    @staticmethod
    def get_process_info() -> Dict[str, float]:
        """获取当前进程内存信息"""
        process = psutil.Process(os.getpid())
        mem_info = process.memory_info()

        total = mem_info.vms / (1024 * 1024)  # 用 VMS 作为总内存
        used = mem_info.rss / (1024 * 1024)  # 用 RSS 作为已使用内存
        free = total - used
        usage = (used / total * 100) if total > 0 else 0

        return {
            'total': round(total, 2),
            'used': round(used, 2),
            'free': round(free, 2),
            'usage': round(usage, 2)
        }

    @staticmethod
    def get_sys_info() -> Dict[str, str]:
        """获取系统信息"""
        hostname = socket.gethostname()

        # 获取IP地址
        ip_address = '127.0.0.1'
        try:
            hostname_ip = socket.gethostbyname(hostname)
            if hostname_ip != '127.0.0.1':
                ip_address = hostname_ip
            else:
                # 尝试获取非本地IP
                with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
                    s.connect(('8.8.8.8', 80))
                    ip_address = s.getsockname()[0]
        except Exception:
            pass

        # 获取操作系统信息
        system = platform.system()
        release = platform.release()

        if system == 'Windows':
            os_name = f'Windows {release}'
        elif system == 'Darwin':
            os_name = f'MacOS {release}'
        elif system == 'Linux':
            os_name = f'Linux {release}'
        else:
            os_name = f'{system} {release}'

        return {
            'computerName': hostname,
            'computerIp': ip_address,
            'osName': os_name,
            'osArch': platform.machine(),
            'userDir': os.getcwd()
        }

    @staticmethod
    def get_mem_info() -> Dict[str, float]:
        """获取内存信息"""
        mem = psutil.virtual_memory()

        return {
            'total': round(mem.total / (1024 ** 3), 2),  # Convert to GB
            'used': round(mem.used / (1024 ** 3), 2),
            'free': round(mem.available / (1024 ** 3), 2),
            'usage': mem.percent
        }

    @staticmethod
    def get_cpu_info() -> Dict[str, Union[int, float]]:
        """获取CPU信息"""
        cpu_times_percent = psutil.cpu_times_percent()

        return {
            'cpuNum': psutil.cpu_count(),
            'used': round(cpu_times_percent.user, 2),
            'sys': round(cpu_times_percent.system, 2),
            'free': round(cpu_times_percent.idle, 2)
        }


if __name__ == '__main__':
    # 测试代码
    monitor = SysMonitorService()
    server_info = monitor.get_server_info()
    print(json.dumps(server_info, indent=2, ensure_ascii=False))
